using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using YooAsset;
/// <summary>
/// Package包数据类
/// </summary>
public class PackageData
{
    [Header("包名")] public string packageName = "DefaultPackage";

    [Header("资源版本")] public string appVersion = "v1.0";

    [Header("下载最大线程数")] public int downloadingMaxNum = 10;
    
    [Header("下载失败重试次数")] public int failedTryAgain = 3;

    public string PackageVersion { get; set; } //远端资源版本
    public ResourceDownloaderOperation downloader { get; set; } = null;

    public PackageData(string _packageName, string _appVersion, int _downloadingMaxNum = 10, int _failedTryAgain = 3)
    {
        this.packageName = _packageName;
        this.appVersion = _appVersion;
        this.downloadingMaxNum = _downloadingMaxNum;
        this.failedTryAgain = _failedTryAgain;
    }

    /// <summary>
    /// 找到需要下载文件后回调
    /// 参数1需要下载文件数量
    /// 参数2需要下载文件大小  单位MB
    /// </summary>
    public Action<int, string> FindDownloadFilesAction;

    /// <summary>
    /// 资源开始下载回调
    /// </summary>
    public DownloaderOperation.OnStartDownloadFile OnStartDownloadAction;

    /// <summary>
    /// 资源正在下载回调
    /// </summary>
    public DownloaderOperation.OnDownloadProgress OnDownloadProgressAction;

    /// <summary>
    /// 资源下载完毕回调
    /// </summary>
    public DownloaderOperation.OnDownloadOver OnDownloadOverAction;

    /// <summary>
    /// 资源下载出错回调
    /// </summary>
    public DownloaderOperation.OnDownloadError OnDownloadErrorAction;

    /// <summary>
    /// 完成资源初始化回调
    /// </summary>
    public Action OnLoadFinishAction;


    public void GetResVersion()
    {
        CoroutineManager.DoCoroutine(GetStaticVersion());
    }

    #region private  Function

    /// <summary>
    /// 获取资源最新版本
    /// </summary>
    /// <returns></returns>
    public IEnumerator GetStaticVersion()
    {
        yield return new WaitForSecondsRealtime(0.5f);

        var package = YooAssets.GetPackage(packageName);
        var operation = package.UpdatePackageVersionAsync();
        yield return operation;

        if (operation.Status == EOperationStatus.Succeed)
        {
            Debug.Log($"包 {packageName} 远端最新版本为: {operation.PackageVersion}");
            PackageVersion = operation.PackageVersion;
            CoroutineManager.DoCoroutine(UpdateManifest());
        }
        else
        {
            Debug.LogWarning($"包 {packageName} 获取资源版本失败：{operation.Error}  使用本地资源加载 !!!");
            PackageVersion = appVersion;
            CoroutineManager.DoCoroutine(UpdateManifest());
        }
    }

    /// <summary>
    /// 更新资源版本号
    /// </summary>
    /// <returns></returns>
    private IEnumerator UpdateManifest()
    {
        yield return new WaitForSecondsRealtime(0.5f);

        bool savePackageVersion = true;
        var package = YooAssets.GetPackage(packageName);
        var operation = package.UpdatePackageManifestAsync(PackageVersion, savePackageVersion);
        yield return operation;

        if (operation.Status == EOperationStatus.Succeed)
        {
            CoroutineManager.DoCoroutine(CreateDownloader());
        }
        else
        {
            Debug.LogWarning($"包 {packageName} 更新资源版本号失败：{operation.Error}");
        }
    }

    /// <summary>
    /// 创建下载器
    /// </summary>
    /// <returns></returns>
    IEnumerator CreateDownloader()
    {
        yield return new WaitForSecondsRealtime(0.5f);

        downloader = YooAssets.CreateResourceDownloader(downloadingMaxNum, failedTryAgain);

        if (downloader.TotalDownloadCount == 0)
        {
            Debug.Log($"包 {packageName} 没有需要下载的文件！");
            ClearCache();
        }
        else
        {
            Debug.Log($"包 {packageName} 共有 {downloader.TotalDownloadCount}个文件需要下载！");

            // 发现新更新文件后，挂起流程系统
            // 注意：开发者需要在下载前检测磁盘空间不足
            int totalDownloadCount = downloader.TotalDownloadCount;
            long totalDownloadBytes = downloader.TotalDownloadBytes;

            float sizeMB = totalDownloadBytes / 1048576f;
            sizeMB = Mathf.Clamp(sizeMB, 0.1f, float.MaxValue);
            string totalSizeMB = sizeMB.ToString("f1");

            FindDownloadFilesAction?.Invoke(totalDownloadCount, totalSizeMB);

            CoroutineManager.DoCoroutine(BeginDownload());
        }
    }

    private IEnumerator BeginDownload()
    {
        // 注册下载回调
        downloader.OnStartDownloadFileCallback = OnStartDownloadAction;
        downloader.OnDownloadProgressCallback = OnDownloadProgressAction;
        downloader.OnDownloadOverCallback = OnDownloadOverAction;
        downloader.OnDownloadErrorCallback = OnDownloadErrorAction;

        OnDownloadOverAction += OnDownloadOverLocalFunction;
        OnDownloadProgressAction += OnDownloadProgressFunction;

        downloader.BeginDownload();
        yield return downloader;

        // 检测下载结果
        if (downloader.Status != EOperationStatus.Succeed)
        {
            Debug.LogWarning($"包 {packageName} 下载资源失败!");
            yield break;
        }

        ClearCache();
    }

    private void OnDownloadProgressFunction(int totaldownloadcount, int currentdownloadcount, long totaldownloadbytes,
        long currentdownloadbytes)
    {
        string currentSizeMB = (currentdownloadbytes / 1048576f).ToString("f1");
        string totalSizeMB = (totaldownloadbytes / 1048576f).ToString("f1");
        Debug.Log(
            $"包 {packageName} 资源正在下载： {currentdownloadcount}/{totaldownloadcount} {currentSizeMB}MB/{totalSizeMB}MB");
    }

    private void OnDownloadOverLocalFunction(bool issucceed)
    {
        CoroutineManager.DoCoroutine(OnDownloadOver());
    }

    private IEnumerator OnDownloadOver()
    {
        yield return 0;
        OnDownloadOverAction -= OnDownloadOverLocalFunction;
        OnDownloadProgressAction -= OnDownloadProgressFunction;
    }

    /// <summary>
    /// 清理缓存文件
    /// </summary>
    private void ClearCache()
    {
        var package = YooAsset.YooAssets.GetPackage(packageName);
        var operation = package.ClearUnusedCacheFilesAsync();
        downloader = null;
        operation.Completed += Operation_Completed;
    }

    private void Operation_Completed(AsyncOperationBase obj)
    {
        //资源加载完毕最终回调
        OnLoadFinishAction?.Invoke();
    }

    #endregion
}